﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.CodeDom.Compiler;
using System.Reflection;
using NHibernate;
using nwrole.toolbox.sync.entity;
using NHibernate.Linq;
using Telerik.Web.Mvc.UI;
using System.IO;

namespace nhEntity_web.Util
{

    public class MyTypeFromAssemblyProvider : NHibernate.Util.ITypeFromAssemblyProvider
    {

        public MyTypeFromAssemblyProvider()
        {
            AssemblyList = new List<Assembly>();
        }

        public List<Assembly> AssemblyList;

        public Type TypeFromAssembly(NHibernate.Util.AssemblyQualifiedTypeName name)
        {
            foreach (var asm in AssemblyList)
            {
                Type t = asm.GetType(name.Type, false, false);
                if (t != null) return t;
            }
            return null;
        }
    }

    public class nhFactory
    {
        // public static IQueryable<object> LoadModel(ISession session, long viewId) {
        public static IDynComp LoadModel(ISession session, long viewId)
        {

            MyTypeFromAssemblyProvider provider = new MyTypeFromAssemblyProvider();
            NHibernate.Util.ReflectHelper.TypeFromAssemblyProvider = provider;

            long entityId = 1;
            IQueryable<nhEntity> entityResult = session.Query<nhEntity>().Where(t => t.Id == entityId); // .FetchMany(c => c.Columns);
            nhEntity entity  = entityResult.FirstOrDefault();

            long entityViewId = 1;
            IQueryable<nhEntityView> entityViewResult = session.Query<nhEntityView>().Where(t => t.Id == entityViewId); // .FetchMany(c => c.Columns);
            nhEntityView entityView = entityViewResult.FirstOrDefault();

            string myCode1 = nhClassGenerator.GenerateClass1(entity, entityView);

            var hej = entityView.Columns;

            CodeDomProvider codeProvider1 = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters cm1 = new CompilerParameters();

            Telerik.Web.Mvc.GridModel gm = new Telerik.Web.Mvc.GridModel();
            if (gm == null)
            {
                var eeee = cm1.GetHashCode();
            }

            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
                if ((!a.FullName.Contains("Anonymously Hosted DynamicMethods Assembly")) &&
                    (!a.FullName.Contains("Microsoft.GeneratedCode")))
                {
                    cm1.ReferencedAssemblies.Add(a.Location);
                }
            }

            cm1.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            var result1 = codeProvider1.CompileAssemblyFromSource(cm1, myCode1);

            if (result1.Errors.HasErrors)
            {
                CompilerError ce = result1.Errors[0];
                string errorStr = ce.ToString();
            }
            provider.AssemblyList.Add(result1.CompiledAssembly);

            codeProvider1.Dispose();

            CodeDomProvider codeProvider2 = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters cm2 = new CompilerParameters();
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if ((!a.FullName.Contains("Anonymously Hosted DynamicMethods Assembly")) &&
                    (!a.FullName.Contains("Microsoft.GeneratedCode")))
                {
                    cm2.ReferencedAssemblies.Add(a.Location);
                }
            }

           // string file2 = result1.CompiledAssembly.Location.Replace(".dll", "2.dll");
           // System.IO.File.Copy(result1.CompiledAssembly.Location, file2);
           // cm2.ReferencedAssemblies.Add(file2);


            string name = Path.GetFileName(result1.CompiledAssembly.Location);
            string fileName2 = "C:/codeplex/nwrole/nhEntity_web/" + name;
            System.IO.File.Copy(result1.CompiledAssembly.Location, fileName2);
            
            string myCode2 = nhClassGenerator.GenerateClass2(entity, entityView);
            var result2 = codeProvider2.CompileAssemblyFromSource(cm2, myCode2);

            if (result2.Errors.HasErrors)
            {
                CompilerError ce = result2.Errors[0];
                string errorStr = ce.ToString();
            }

            string asmName = name.Replace(".dll","");

            // var repository = result1.CompiledAssembly.CreateInstance("mynamespace2.MyRepository", false);


            AppDomain.CurrentDomain.Load(result1.CompiledAssembly.GetName());

            object ooo = result1.CompiledAssembly.CreateInstance("mynamespace.Instrument", false);
            IDynComp gridComponent = result2.CompiledAssembly.CreateInstance("mynamespace2.GridComponent1", false) as IDynComp;


            //string s1 = "mynamespace.Instrument, {bob}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null".Replace("{bob}", asmName);
            //string s2 = "{bob}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null".Replace("{bob}", asmName);

            //System.Type type1 = System.Type.GetType(s1);
            //System.Type type2 = System.Type.GetType("mynamespace.Instrument");
            // Assembly assembly = Assembly.Load(s2);



            // Assembly.LoadFrom(result.CompiledAssembly.Location);



            gridComponent.Test(result1.CompiledAssembly);

            

            // plopp.test();

            //int a22 = 1;

           
            return gridComponent;
        }

    }
}

// http://www.fidelitydesign.net/?p=208